package com.focusai.efairy.business.location;


import android.content.Context;

import com.focusai.efairy.model.location.Location;
import com.focusai.efairy.model.location.LocationCallback;
import com.focusai.efairy.model.location.LocationManager;
import com.focusai.efairy.utils.ActivityUtils;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;


public class LocationModel {

    private ArrayList<WeakReference<ILocationUpdateCallback>> mClients = new ArrayList<>();

    public interface ILocationUpdateCallback {
        int LOCATION_ERROR_TYPE_PERMISSION = 0;
        int LOCATION_ERROR_TYPE_ALLOW_MOCK = 1;
        int LOCATION_ERROR_TYPE_OTHER = 2;

        void locationSuccess(Location location);

        void locationFail(int errorType);
    }

    public enum UpdateType {
        LOCATION_SUCCESS,
        LOCATION_FAIL
    }

    /**
     * 通知所有观察者
     */
    private void notifyAllClients(UpdateType type, Object... args) {
        Iterator<WeakReference<ILocationUpdateCallback>> it = mClients.iterator();
        while (it.hasNext()) {
            ILocationUpdateCallback c = it.next().get();
            if (c == null) {
                it.remove();
                continue;
            }

            switch (type) {
                case LOCATION_SUCCESS:
                    if (args != null && args.length > 0) {
                        if (args[0] != null) {
                            c.locationSuccess((Location) args[0]);
                        }
                    }
                    break;
                case LOCATION_FAIL:
                    if (args != null && args.length > 0) {
                        if (args[0] != null) {
                            c.locationFail((int) args[0]);
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }


    public void register(ILocationUpdateCallback client) {
        if (client == null) {
            return;
        }

        Iterator<WeakReference<ILocationUpdateCallback>> it = mClients.iterator();
        while (it.hasNext()) {
            ILocationUpdateCallback c = it.next().get();
            if (c == null) {
                it.remove();
            } else if (c == client) {
                return;
            }
        }

        mClients.add(new WeakReference<>(client));
    }

    public void unregister(ILocationUpdateCallback client) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            ILocationUpdateCallback c = mClients.get(i).get();
            if (c == null) {
                mClients.remove(i);
            } else if (c == client) {
                mClients.remove(i);
            }
        }
    }

    private Context mCtx;

    public LocationModel(Context context) {
        mCtx = context;
        initLocation(mCtx);
    }

    private LocationManager mLocationManager;

    private void initLocation(final Context context) {
        mLocationManager = LocationManagerFactory.getLocationManager(context);
        mLocationManager.setLocationCallback(new LocationCallback() {

            @Override
            public void locationSuccess(Location location) {
                if (ActivityUtils.isActivityFinishing(context)) {
                    return;
                }
                stopLocation();
                notifyAllClients(UpdateType.LOCATION_SUCCESS, location);
            }

            @Override
            public void locationFail(int errorCode, String errorMessage) {
                if (ActivityUtils.isActivityFinishing(context)) {
                    return;
                }

                stopLocation();
                notifyAllClients(UpdateType.LOCATION_FAIL, ILocationUpdateCallback.LOCATION_ERROR_TYPE_OTHER);

//                if (errorCode == permissionErrorCode(mLocationManager.getLocationType())) {
//                    notifyAllClients(UpdateType.LOCATION_FAIL, ILocationUpdateCallback.LOCATION_ERROR_TYPE_PERMISSION);
//                } else if (errorCode == LocationManagerFactory.ERROR_MOCK_LOCATION) {
//                    notifyAllClients(UpdateType.LOCATION_FAIL, ILocationUpdateCallback.LOCATION_ERROR_TYPE_ALLOW_MOCK);
//                } else {
//                    notifyAllClients(UpdateType.LOCATION_FAIL, ILocationUpdateCallback.LOCATION_ERROR_TYPE_OTHER);
//                }

            }
        });
    }



    private void switchLocationType(int locationType) {
//        switch (locationType) {
//            case LocationManagerFactory.TYPE_BD:
//                TeamPrefs.setLocationType(LocationManagerFactory.TYPE_TENCENT);
//                break;
//            case LocationManagerFactory.TYPE_TENCENT:
//            case LocationManagerFactory.TYPE_AMAP:
//                TeamPrefs.setLocationType(LocationManagerFactory.TYPE_BD);
//                break;
//            default:
//                break;
//        }

        initLocation(mCtx);
    }


    public void startLocation() {
        startLocation(false);
    }

    public void startLocation(boolean switchClient) {
        if (switchClient) {
            switchLocationType(mLocationManager.getLocationType());
        }

        if (!mLocationManager.isStarted()) {
            mLocationManager.startLocation();
        }
    }

    public void stopLocation() {
        if (mLocationManager != null) {
            mLocationManager.stopLocation();
        }
    }

}